package com.waylau.spring.boot.blog.service;

import javax.transaction.Transactional;

import com.waylau.spring.boot.blog.domain.*;
import com.waylau.spring.boot.blog.repository.GenreRepository;
import com.waylau.spring.boot.blog.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import com.waylau.spring.boot.blog.domain.es.EsBlog;
import com.waylau.spring.boot.blog.repository.BlogRepository;

import java.util.*;

/**
 * Blog 服务.
 * 
 * @since 1.0.0 2017年4月7日
 * @author <a href="https://waylau.com">Way Lau</a>
 */
@Service
public class BlogServiceImpl implements BlogService {

	@Autowired
	private BlogRepository blogRepository;
	@Autowired
	private EsBlogService esBlogService;
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private GenreRepository genreRepository;

 
	/* (non-Javadoc)
	 * @see com.waylau.spring.boot.blog.service.BlogService#saveBlog(com.waylau.spring.boot.blog.domain.Blog)
	 */
	@Transactional
	@Override
	public Blog saveBlog(Blog blog) {
		boolean isNew = (blog.getId() == null);
		EsBlog esBlog = null;
		
		Blog returnBlog = blogRepository.save(blog);
		
		if (isNew) {
			esBlog = new EsBlog(returnBlog);
		} else {
			esBlog = esBlogService.getEsBlogByBlogId(blog.getId());
			esBlog.update(returnBlog);
		}
		
		esBlogService.updateEsBlog(esBlog);
		return returnBlog;
	}

	/* (non-Javadoc)
	 * @see com.waylau.spring.boot.blog.service.BlogService#removeBlog(java.lang.Long)
	 */
	@Transactional
	@Override
	public void removeBlog(Long id) {
		//假删除
		Blog blog = blogRepository.findByIdAndStatus(id,0);
		blog.setStatus(1);
		blogRepository.save(blog);
		EsBlog esblog = esBlogService.getEsBlogByBlogId(id);
		if(esblog!=null){
			esBlogService.removeEsBlog(esblog.getId());
		}
	}

	/* (non-Javadoc)
	 * @see com.waylau.spring.boot.blog.service.BlogService#getBlogById(java.lang.Long)
	 */
	@Override
	public Blog getBlogById(Long id) {
		return blogRepository.findByIdAndStatus(id,0);
	}

	@Override
	public Page<Blog> listBlogsByTitleVote(User user, String title, Pageable pageable) {
		// 模糊查询
		title = "%" + title + "%";
		//Page<Blog> blogs = blogRepository.findByUserAndTitleLikeOrderByCreateTimeDesc(user, title, pageable);
		String tags = title;
		Page<Blog> blogs = blogRepository.findByTitleLikeAndUserOrTagsLikeAndUserAndStatusOrderByCreateTimeDesc(title,user, tags,user, 0, pageable);
		return blogs;
	}

	@Override
	public Page<Blog> listBlogsByTitle(String title, Pageable pageable) {
		// 模糊查询
		title = "%" + title + "%";
		Page<Blog> blogs = blogRepository.findByTitleLikeAndStatusOrderByCreateTimeAsc(title,0, pageable);
		return blogs;
	}

	@Override
	public Page<Blog> listBlogsByTitleVoteAndSort(User user, String title, Pageable pageable) {
		// 模糊查询
		title = "%" + title + "%";
		Page<Blog> blogs = blogRepository.findByUserAndTitleLikeAndStatus(user, title, 0 ,pageable);
		return blogs;
	}

	@Override
	public Page<Blog> listBlogsByIds(Collection c, Pageable pageable) {
		Page<Blog> blogs = blogRepository.findByIdInAndStatus(c,0,pageable);
		return blogs;
	}

	@Override
	public Page<Blog> listBlogsByCatalog(Catalog catalog, Pageable pageable) {
		Page<Blog> blogs = blogRepository.findByCatalogAndStatus(catalog,0, pageable);
		return blogs;
	}

	@Override
	public void readingIncrease(Long id) {
		Blog blog = blogRepository.findByIdAndStatus(id,0);
		blog.setReadSize(blog.getReadSize()+1);
		this.saveBlog(blog);
	}

	@Override
	public Blog createComment(Long blogId, String commentContent) {
		Blog originalBlog = blogRepository.findByIdAndStatus(blogId,0);
		User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
		Comment comment = new Comment(user, commentContent);
		originalBlog.addComment(comment);
		return this.saveBlog(originalBlog);
	}

	@Override
	public void removeComment(Long blogId, Long commentId) {
		Blog originalBlog = blogRepository.findByIdAndStatus(blogId,0);
		originalBlog.removeComment(commentId);
		this.saveBlog(originalBlog);
	}

	@Override
	public Blog createVote(Long blogId) {
		Blog originalBlog = blogRepository.findByIdAndStatus(blogId,0);
		User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
		Vote vote = new Vote(user);
		boolean isExist = originalBlog.addVote(vote);
		if (isExist) {
			throw new IllegalArgumentException("该用户已经点过赞了");
		}
		return this.saveBlog(originalBlog);
	}

	@Override
	public void removeVote(Long blogId, Long voteId) {
		Blog originalBlog = blogRepository.findByIdAndStatus(blogId,0);
		originalBlog.removeVote(voteId);
		this.saveBlog(originalBlog);
	}

	@Override
	public Blog collectBlog(Long blogId) {
		User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		Blog blog = blogRepository.findByIdAndStatus(blogId,0);
		//Set<Blog> set = new HashSet<Blog>();
		//set.add(blog);
		//user.setCollectBlogs(set);
		user.getCollectBlogs().add(blog);
		userRepository.save(user);
		return blog;
	}

	@Override
	public void cancelCollectBlog(Long blogId) {
		User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		user = userRepository.findOne(user.getId());
		Blog blog = blogRepository.findByIdAndStatus(blogId,0);
		user.getCollectBlogs().remove(blog);
		userRepository.save(user);
	}

	@Override
	public HashMap<String, Integer> voteTop5() {
		List<Blog> blogs = blogRepository.findByStatus(0);
		HashMap<String,Integer> genres = new HashMap<>();
		blogs.forEach(a->{
			if(a.getGenre()!=null){
				if(genres.get(a.getGenre().getName())!=null){
					genres.put(a.getGenre().getName(),genres.get(a.getGenre().getName())+a.getVoteSize());
				}else{
					genres.put(a.getGenre().getName(),a.getVoteSize());
				}
			}
		});
		Set<Map.Entry<String,Integer>> set = genres.entrySet();
		List<Map.Entry<String,Integer>> list = new LinkedList<>(set);
		Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
			@Override
			public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
				return o2.getValue()-o1.getValue();
			}
		});
		genres.clear();
		for(int i=0;i<5&&i<list.size();i++){
			genres.put(list.get(i).getKey(),list.get(i).getValue());
		}
		return genres;
	}

	@Override
	public List<Blog> listTopNByGenre(Long genreId, Integer n) {

		Genre genre = genreRepository.findOne(genreId);

		if(n==4){
			return blogRepository.findTop4ByGenreAndStatusOrderByReadSizeDesc(genre,0);
		}else if(n==3){
			return blogRepository.findTop3ByGenreAndStatusOrderByReadSizeDesc(genre,0);
		}else if(n==2){
			return blogRepository.findTop2ByGenreAndStatusOrderByReadSizeDesc(genre,0);
		}else{
			return blogRepository.findTop1ByGenreAndStatusOrderByReadSizeDesc(genre,0);
		}
	}
}
